<?php


namespace App\Admin\Extensions\OAuth;


use Cann\Admin\OAuth\Models\AdminUserThirdPfBind;
use Cann\Admin\OAuth\ThirdAccount\Thirds\ThirdAbstract;
use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Request;
use Illuminate\Support\Str;

/**
 * 飞书联合登录
 */
class Feishu extends ThirdAbstract
{
    public function getUserByThird(array $thirdUser)
    {
        if (!isset($thirdUser['id']) || !$thirdUser['id']) {
            throw new \Exception('Not Found Third Id');
        }

        $user = AdminUserThirdPfBind::getUserByThird($this->getPlatform(), $thirdUser['id']);

        // 根据第三方账号创建本地账号
        if (!$user && config('admin-oauth.allowed_auto_create_account_by_third')) {

            $userModel = config('admin.database.users_model');
            $username = $thirdUser['user_name'];

            // username 已存在
            if ($userModel::where('username', $thirdUser['name'])->first()) {
                $username = \Str::random(16);
            }

            $user = $userModel::create([
                'username' => $username,
                'password' => \Hash::make(Str::random(64)),
                'name' => $thirdUser['name'],
                'avatar' => $thirdUser['avatar']
            ]);

            // 建立飞书和本地账号的绑定关系
            $this->bindUserByThird($user, $thirdUser);
        } else {
            //每一次都更新头像和名称
            $user->name = $thirdUser['name'];
            $user->avatar = $thirdUser['avatar'];
            $user->save();
        }
        return $user;
    }

    public function getThirdUser(array $params)
    {
        // TODO: Implement getThirdUser() method.
        $config = Config::get('admin-oauth.services.feishu');
        $code = Arr::get($params, 'code');
        $appAccessToken = $this->getAppAccessToken();
        $userBase = $this->getUserBase($code, $appAccessToken);

        if (strlen(Arr::get($userBase, 'data.access_token', ''))) {
            Cache::put($config['user_access_token_cache_key'], Arr::get($userBase, 'data.access_token', ''), Arr::get($userBase, 'data.expires_in', 6900));
        }

        return [
            'id' => Arr::get($userBase, 'data.open_id'),
            'user_name' => Arr::get($userBase, 'data.en_name'),
            'name' => Arr::get($userBase, 'data.name'),
            'avatar' => Arr::get($userBase, 'data.avatar_big'),
        ];
    }

    /**
     * 获取登录跳转地址
     * @param array $params
     * @return string
     */
    public function getAuthorizeUrl(array $params)
    {
        // TODO: Change the autogenerated stub
        $config = Config::get('admin-oauth.services.feishu');
        $this->redirectUrl = $config['redirect_url'];
        return sprintf("%s/authen/v1/index?app_id=%s&redirect_uri=%s", rtrim($config['base_uri'],'/'), $config['app_id'], urlencode($this->redirectUrl));
    }


    /**
     * 获取app_access_token
     * @return mixed
     */
    public function getAppAccessToken()
    {
        $cacheKey = __METHOD__;
//        Cache::forget($cacheKey);
        $appAccessToken = Cache::get($cacheKey, function () use ($cacheKey) {
            $config = Config::get('admin-oauth.services.feishu');
            $client = new Client([
                'base_uri' => $config['base_uri'],
                'timeout' => 30
            ]);
            $response = $client->request('POST', 'auth/v3/app_access_token/internal/', [
                RequestOptions::HTTP_ERRORS => false,
                RequestOptions::VERIFY => false,
                RequestOptions::JSON => [
                    'app_id' => $config['app_id'],
                    'app_secret' => $config['app_secret']
                ]
            ]);

            $data = \json_decode($response->getBody()->getContents(), true);
            if (strlen(Arr::get($data, 'app_access_token', ''))) {
                Cache::put($cacheKey, Arr::get($data, 'app_access_token', ''), Arr::get($data, 'expire', 7200));
            }
            return Arr::get($data, 'app_access_token', false);
        });
        return $appAccessToken;
    }

    public function getUserBase($code = '', $appAccessToken = '')
    {
        $config = Config::get('admin-oauth.services.feishu');
        $client = new Client([
            'base_uri' => $config['base_uri'],
            'timeout' => 30
        ]);

        $response = $client->request('POST', 'authen/v1/access_token', [
            RequestOptions::HTTP_ERRORS => false,
            RequestOptions::VERIFY => false,
            RequestOptions::JSON => [
                'app_access_token' => $appAccessToken,
                'grant_type' => 'authorization_code',
                'code' => $code
            ]
        ]);
        return \json_decode($response->getBody()->getContents(), true);
    }
}
